package com.exam.service.serviceImpl;

import com.exam.dataobject.User;
import com.exam.dataobject.mapper.UserMapper;
import com.exam.enums.ResultEnum;
import com.exam.enums.UserStatusEnum;
import com.exam.exception.ExaminationException;
import com.exam.repository.UserRepository;
import com.exam.repository.UserTypeRepository;
import com.exam.service.UserService;
import com.exam.utils.CookieUtil;
import com.exam.utils.RedisUserIdUtil;
import com.exam.utils.ResultVOUtil;
import com.exam.utils.UserUtils;
import com.exam.utils.constant.CookieConstant;
import com.exam.utils.constant.RedisConstant;
import com.exam.vo.ResultVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.validation.BindingResult;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * Created by v
 * Date:2019/1/6
 * Time:20:25
 */
@Service
@Slf4j
public class UserServiceImpl implements UserService {


    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private UserTypeRepository userTypeRepository;

    @Override
    public User getUserByUserName(String userName) {
        return userRepository.findByUserName(userName);
    }

    @Override
    public void ifUserExist(String userName) {
//        User user = userRepository.findByUserName(userName);
//        if (user != null) {
//            log.error("【用户名已经被注册】 userName={}", userName);
//            throw new ExaminationException(UserStatusEnum.USER_NAME_EXIST.getCode(), UserStatusEnum.USER_NAME_EXIST.getMessage());
//        }
    }

    @Override
    public void saveRegisterUser(Map<String, Object> registerInfo, BindingResult bindingResult, HttpServletRequest request) {

        if (bindingResult.hasErrors()) {
            log.error("【用户注册】参数不正确, registerInfo={}", registerInfo);
            throw new ExaminationException(ResultEnum.USER_REGISTER_ERROR.getCode(), bindingResult.getFieldError().getDefaultMessage());
        }
        //检查用户名是否被注册
        if (userRepository.findByUserName(registerInfo.get("userName").toString()) != null) {
            log.error("【用户名已经被注册】 userName={}", registerInfo.get("userName").toString());
            throw new ExaminationException(UserStatusEnum.USER_NAME_EXIST.getCode(), UserStatusEnum.USER_NAME_EXIST.getMessage());
        }
        //检查数据是否正确，比如验证码，两次密码是否一致
        Map<String, String> map = UserUtils.checkUserForm(registerInfo, request);
        if (Integer.parseInt(map.get("code")) != UserStatusEnum.USER_SUCCESS.getCode()) {
            log.error("【用户注册】参数不正确, registerInfo={}", registerInfo);
            throw new ExaminationException(Integer.parseInt(map.get("code")), map.get("message"));
        }
        ;
        //检查用户是否已经注册
        if (userRepository.findByUserPhone(registerInfo.get("userPhone").toString()) != null) {
            log.error("【用户已经注册】, userPhone={}", registerInfo.get("userPhone").toString());
            throw new ExaminationException(UserStatusEnum.USER_RESISTERED.getCode(), UserStatusEnum.USER_RESISTERED.getMessage());
        }

        userMapper.registerUser(registerInfo);
    }

    @Override
    public Map<String, Object> login(Map<String, Object> userLogin, HttpServletRequest request, HttpServletResponse httpResponse) {
        //检查是否注册,
        Map<String, Object> userMap = userMapper.getUserByNameOrPhoneOrEmail(userLogin.get("userName").toString()).get(0);

        if (userMap.get("user_name")==(null)) {
            log.error("【用户不存在】 userName={}", userLogin.get("userName").toString());
            throw new ExaminationException(UserStatusEnum.USER_NOT_REGISTER.getCode(), UserStatusEnum.USER_NOT_REGISTER.getMessage());
        }
        //检查账号密码是否正确
        if (!userMap.get("password").equals(userLogin.get("password").toString())) {
            log.error("【用户密码不正确】 username={} userPassword={}", userLogin.get("userName").toString(), userLogin.get("password").toString());
            throw new ExaminationException(UserStatusEnum.USER_PASSWORD_ERROR.getCode(), UserStatusEnum.USER_PASSWORD_ERROR.getMessage());
        }
        //验证码是否正确
        if (!request.getSession().getAttribute(userLogin.get("userCaptchaKey").toString()).toString().equalsIgnoreCase(userLogin.get("userCaptcha").toString())) {
            log.error("【用户验证码不正确】 captcha={}", userLogin.get("userCaptcha").toString());
            throw new ExaminationException(UserStatusEnum.USER_CAPTCHA_ERROR.getCode(), UserStatusEnum.USER_CAPTCHA_ERROR.getMessage());
        }
        //设置token至redis
        String token = UUID.randomUUID().toString();
        Integer expire = RedisConstant.EXPIRE;

        redisTemplate.opsForValue().set(String.format(RedisConstant.TOKEN_PREFIX, token), String.valueOf(userMap.get("user_id")), expire, TimeUnit.SECONDS);
        // 设置token至cookie
        CookieUtil.set(httpResponse, CookieConstant.TOKEN, token, expire);
        Map<String, Object> map = new HashMap<>();
        map.put("type", userTypeRepository.findByUserTypeId(Integer.valueOf(userMap.get("user_type_id").toString())).getUserType());
        //用户登录后，从数据库获得loginTime，然后把当前时间存到数据库loginTime
        User user = userRepository.findByUserId(Integer.valueOf(userMap.get("user_id").toString()));
        user.setLoginTime(new Date());
        userRepository.save(user);
        request.getSession().setAttribute(user.getUserId() + "loginTime", user.getLoginTime().getTime() / 1000);

        return map;
    }

    @Override
    public ResultVO isLogin(HttpServletRequest request) {

        String userIdString = RedisUserIdUtil.getUserId(request, redisTemplate);
        Map<String, Object> map = new HashMap<>();
        if (userIdString == null) {
            //说明为空，就是没登录
            map.put("type", null);
            return ResultVOUtil.error(ResultEnum.UNLOGIN.getCode(), ResultEnum.UNLOGIN.getMessage());
        } else {
            //说明已经登录了
            User user = userRepository.findByUserId(Integer.valueOf(userIdString));
            map.put("type", userTypeRepository.findByUserTypeId(user.getUserTypeId()).getUserType());
        }
        return ResultVOUtil.success(map);
    }

    @Override
    public void logout(HttpServletRequest request, HttpServletResponse response) {
        //从cookie里查询
        Cookie cookie = CookieUtil.get(request, CookieConstant.TOKEN);
        if (cookie != null) {
            //2. 清除redis
            redisTemplate.opsForValue().getOperations().delete(String.format(RedisConstant.TOKEN_PREFIX, cookie.getValue()));
            //3. 清除cookie
            CookieUtil.set(response, CookieConstant.TOKEN, null, 0);
        } else {
            log.error("【用户未登录】");
            throw new ExaminationException(UserStatusEnum.USER_NOT_LOGIN.getCode(), UserStatusEnum.USER_NOT_LOGIN.getMessage());
        }
    }

    @Override
    public Map<String, Object> getUserInfo(Integer userId) {

        User user = userRepository.findByUserId(userId);
        Map<String, Object> map = new HashMap<>();
        map.put("userName", user.getUserName());
        map.put("userPhone", user.getUserPhone());
        map.put("eMail", user.getEMail());
        map.put("userType", userTypeRepository.findByUserTypeId(user.getUserTypeId()).getUserType());

        return map;
    }

    @Override
    public void changeUserInfo(Map<String, Object> changeInfo, HttpServletRequest request) {

        String userId = RedisUserIdUtil.getUserId(request, redisTemplate);
        changeInfo.put("userId", userId);

        userMapper.updateUserInfo(changeInfo);
    }
}
